package edu.hawaii.its381b.client;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.dom.client.AudioElement;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.dom.client.MediaElement;
import com.google.gwt.media.client.Audio;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;

public class MapItems {

	//The constants below swap IDs and values for meaningful text. This is for easier code readability
	private final int xLoc = 0,yLoc = 1, offsetByOne = 1, numberOfShells = 5,
	netWidthPx=400,netHeightPx= 180, netStartingXPosition = 700, columsOfNetAnimation = 10, 
	netWidthAdjustment = 50, netHeightAdjustment = 100, netDropSpeed =10 ,twoSeconds= 48,
	barWidth = 250, barHeight = 50,
	restartWidth = 400, restartHeight = 200,
	restartXDraw =  100,restartYDraw =  350,
	topLeft=1,topCenter=2,topRight=3,middleLeft=4,middleRight=5,bottomLeft=6,bottomCenter=7,bottomRight=8,
	itemPixelSize = 50,  	//Item pixel size is the default height and width of all items
	coneShell = 1, leftHandedShell = 2,hiddenShell = 3, elegantShell = 4, jewelledShell = 5,
	coneCrab = 1, leftHandedCrab = 2,hiddenCrab= 3, elegantCrab = 4, jewelledCrab = 5,
	kelpItem1 = 6, kelpItem2 = 7, kelpItem3 = 8,
	firstKelpLeaf = 0,secondKelpLeaf = 1,thirdKelpLeaf = 2,lastKelpLeaf = 3,
	gameItemCount = 8,
	correctShellFound = 1, lostACrab = 9, storeTank = 9, gameOver=11,
	lastNetFrameX=3600,lastNetFrameY=900,  
	statusInPlay= 0, statusOnBarReady = 1,statusInTankSpot = 2, statusInHome = 3;

	//					Map Data
	private int currentItemLocX,currentItemLocY, 
	mapRows,mapColumns, mapWidth, mapHeight,
	canvasWidth,canvasHeight,crabBoundary,controlBarThickness,distanceFromMapEdge,
	topLeftMapVisibleX,topLeftMapVisibleY, 	//variables to track what selection of the map has been drawn
	bottomRightMapDrawX,bottomRightMapDrawY,
	//		Variables to track where on the Canvas an item will be drawn
	currentPlayerCrab, currentPlayerCanvasX, currentPlayerCanvasY,
	//		Crab Net variables
	netCanvasX, netCanvasY, netCanvasXIncrement,netCanvasYIncrement,
	crabCanvasX,crabCanvasY, crabCanvasXIncrement,crabCanvasYIncrement,
	//		Variables to keep track of what frames for animation begin, end, and current
	crabGoingHomeFrame, gameOverFrame,
	kelpEatFrame,kelpEatLastFrame, kelpFrame, kelpLastFrame, kelpCurrentFrame,
	lostCrabFrame, lostCrabLastFrame,
	animationLastFame[] = new int[11+offsetByOne],
	crabOnTankBarX,crabOnBarY,crabOnStartBarX,
	coneStartPosition, leftHandedStartPosition,hiddenStartPosition, elegantStartPosition, jewelledStartPosition,
	coneLostPosition, leftHandedLostPosition,hiddenLostPosition, elegantLostPosition, jewelledLostPosition,
	// Keep track of Item Locations
	gameOverCanvasY,
	gameItemXYLocations[][] = new int [gameItemCount+offsetByOne][2],
	gameItemGridLocations[][] = new int [gameItemCount+offsetByOne][2],
	gameItemCurrentCanvasXY[][] = new int [gameItemCount+offsetByOne][2],
	quadrantLocations[] = new int[gameItemCount+offsetByOne],
	crabLostPosistions[] = new int[5+offsetByOne],
	// Variables to keep track of Crabs in play, out of play 
	sideLineStatus[] = new int [gameItemCount+offsetByOne+offsetByOne];

	private boolean lostCrabAnimantionStillGoing, canPlayEat,
	crabAteAKelpLeaf, gameEnded,
	kelpItemIsGone [] =new boolean[9],
	kelpNotEaten[][] = new boolean[9][4];

	private ImageElement itemImages[] = new ImageElement[gameItemCount+offsetByOne],
	shellOriginalImages[] = new ImageElement[numberOfShells+offsetByOne],
	crabImage[] = new ImageElement[numberOfShells+offsetByOne],
	lostCrabImage[] = new ImageElement[numberOfShells+offsetByOne],
	gameOverImage[] = new ImageElement[numberOfShells+offsetByOne],
	shellWithCrabImage[] = new ImageElement[numberOfShells+offsetByOne],
	crabGoingHomeAnimImage[] = new ImageElement[numberOfShells+offsetByOne],
	crabEatKelpAnimImage[] = new ImageElement[numberOfShells+offsetByOne],
	itemCurrentImage,
	netAnimationImage, currentLostCrabImage,
	kelpFullImage,kelpLeafAnimBaseImage,
	kelpLeafAnim1Image ,kelpLeafAnim2Image ,kelpLeafAnim3Image ,kelpLeafAnim4Image,
	restartImage, blackBarImage; 

	private Audio eatSoundFX = Audio.createIfSupported();

	private Canvas canvas;
	//END OF DECLARATIONS



	public MapItems(int mapRowAmount, int mapColumnsAmount,
			int gameCanvasWidth, int gameCanvasHeight,  
			int crabBoundaryAmount, int controlBarThicknessAmount, int distanceFromMapEdgeAmount,
			Canvas gameCanvas){

		//Note: they may all be 71 now, but they are loaded this way to make it easy to change
		// one any time I make a new animation
		animationLastFame[coneShell]=71;
		animationLastFame[leftHandedShell]=71;
		animationLastFame[hiddenShell]=71;
		animationLastFame[elegantShell]=71;
		animationLastFame[jewelledShell]=71;
		animationLastFame[gameOver]=71;

		loadShellImages();
		loadKelpImages();
		loadBarReadyImages();
		loadCrabInShellImages();
		loadCrabIsLostImages();
		loadAnimationImages();
		loadGameOverImages();

		SafeUri blackBarURI = HermitCrabResources.INSTANCE.blackBar().getSafeUri();
		blackBarImage =  ImageElement.as((new Image(blackBarURI )).getElement());

		initializeMapItems(mapRowAmount, mapColumnsAmount,
				gameCanvasWidth,gameCanvasHeight,
				crabBoundaryAmount, controlBarThicknessAmount, distanceFromMapEdgeAmount,
				gameCanvas);
		loadSoundFX();
	}

	public void initializeMapItems(int mapRowAmount, int mapColumnsAmount,
			int gameCanvasWidth, int gameCanvasHeight,
			int crabBoundaryAmount, int controlBarThicknessAmount, int distanceFromMapEdgeAmount,
			Canvas gameCanvas){
		mapRows = mapRowAmount;
		mapColumns = mapColumnsAmount;
		mapWidth = this.mapRows * this.itemPixelSize;
		mapHeight = this.mapColumns * this.itemPixelSize;
		canvas = gameCanvas;
		canvasWidth = gameCanvasWidth;
		canvasHeight = gameCanvasHeight;
		crabBoundary = crabBoundaryAmount;
		controlBarThickness = controlBarThicknessAmount;
		distanceFromMapEdge = distanceFromMapEdgeAmount;
		crabOnStartBarX = gameCanvasWidth - barWidth;
		crabOnBarY = gameCanvasHeight - barHeight;

		loadStartingVariables();
		loadCrabStartAndLostPostistions();

		//Map is divided into 8 areas. Fill them with 1 item each(there are 8 items) 
		fillQuadrants();

		//Fill 8 items with their X,Y locations.
		for(int currentItem = coneShell; currentItem <= kelpItem3 ; currentItem++){
			this.gameItemXYLocations[currentItem][xLoc] = randomMapLocationX(currentItem);
			this.gameItemXYLocations[currentItem][yLoc] = randomMapLocationY(currentItem);
			kelpItemIsGone[currentItem] = false;
			kelpNotEaten[currentItem][firstKelpLeaf]= true;
			kelpNotEaten[currentItem][secondKelpLeaf]= true;
			kelpNotEaten[currentItem][thirdKelpLeaf]= true;
			kelpNotEaten[currentItem][lastKelpLeaf]= true;
			if(currentItem<=jewelledShell){
				itemImages[currentItem] = shellOriginalImages[currentItem];
				sideLineStatus[currentItem] =  statusOnBarReady;
			}
		}
		updateItemGridLocations();
		updateBar();

		sideLineStatus[coneCrab] =  statusInPlay;
		sideLineStatus[storeTank] =  statusInPlay;
	}

	//LOAD Start *******************************************
	private void loadStartingVariables(){
		crabOnTankBarX = 0;
		currentPlayerCrab = 1;
		netCanvasX = 650;
		gameOverFrame = 0;
		crabGoingHomeFrame = 0;
		gameOverFrame = 0;
		kelpEatFrame = 0;
		kelpEatLastFrame = 71;
		kelpFrame = 0;
		kelpLastFrame = 71;
		kelpCurrentFrame=0;
		lostCrabFrame = 0;
		lostCrabLastFrame = 59;
		gameOverCanvasY = -400;
		lostCrabAnimantionStillGoing = true;
		canPlayEat=true;
		crabAteAKelpLeaf = false;
		gameEnded = false;
	}

	private void loadCrabStartAndLostPostistions(){
		coneStartPosition = crabOnStartBarX;
		leftHandedStartPosition = crabOnStartBarX + itemPixelSize;
		hiddenStartPosition = crabOnStartBarX + itemPixelSize*2;
		elegantStartPosition = crabOnStartBarX + itemPixelSize*3;
		jewelledStartPosition = crabOnStartBarX + itemPixelSize*4;

		coneLostPosition = crabOnTankBarX;
		leftHandedLostPosition = crabOnTankBarX + itemPixelSize;
		hiddenLostPosition = crabOnTankBarX + itemPixelSize*2;
		elegantLostPosition = crabOnTankBarX + itemPixelSize*3;
		jewelledLostPosition = crabOnTankBarX + itemPixelSize*4;

		loadCrabLostPositions();
	}
	private void loadShellImages(){
		SafeUri shellConeURI = HermitCrabResources.INSTANCE.shellCone().getSafeUri();
		shellOriginalImages[coneShell] =  ImageElement.as((new Image(shellConeURI )).getElement());

		SafeUri shellLeftHandedURI = HermitCrabResources.INSTANCE.shellLeftHanded().getSafeUri();
		shellOriginalImages[leftHandedShell] = ImageElement.as((new Image(shellLeftHandedURI)).getElement());

		SafeUri shellHiddenURI = HermitCrabResources.INSTANCE.shellHidden().getSafeUri();
		shellOriginalImages[hiddenShell] = ImageElement.as((new Image(shellHiddenURI )).getElement());

		SafeUri shellElegantURI = HermitCrabResources.INSTANCE.shellElegant().getSafeUri();
		shellOriginalImages[elegantShell] = ImageElement.as((new Image(shellElegantURI)).getElement());

		SafeUri shellJewelledURI = HermitCrabResources.INSTANCE.shellJewelled().getSafeUri();
		shellOriginalImages[jewelledShell] = ImageElement.as((new Image(shellJewelledURI)).getElement());
	}

	private void loadKelpImages(){
		SafeUri kelpLeafAnimBaseURI = HermitCrabResources.INSTANCE.kelpLeafAnimBase().getSafeUri();
		kelpLeafAnimBaseImage = ImageElement.as((new Image(kelpLeafAnimBaseURI)).getElement());
		itemImages[kelpItem1] = kelpLeafAnimBaseImage;
		itemImages[kelpItem2] = kelpLeafAnimBaseImage;    	
		itemImages[kelpItem3] = kelpLeafAnimBaseImage;

		SafeUri kelpLeafAnim1URI = HermitCrabResources.INSTANCE.kelpLeafAnim1().getSafeUri();
		kelpLeafAnim1Image = ImageElement.as((new Image(kelpLeafAnim1URI)).getElement());

		SafeUri kelpLeafAnim2URI = HermitCrabResources.INSTANCE.kelpLeafAnim2().getSafeUri();
		kelpLeafAnim2Image = ImageElement.as((new Image(kelpLeafAnim2URI)).getElement());

		SafeUri kelpLeafAnim3URI = HermitCrabResources.INSTANCE.kelpLeafAnim3().getSafeUri();
		kelpLeafAnim3Image = ImageElement.as((new Image(kelpLeafAnim3URI)).getElement());

		SafeUri kelpLeafAnim4URI = HermitCrabResources.INSTANCE.kelpLeafAnim4().getSafeUri();
		kelpLeafAnim4Image = ImageElement.as((new Image(kelpLeafAnim4URI)).getElement());

		SafeUri kelpFullImageURI = HermitCrabResources.INSTANCE.kelpFull().getSafeUri();
		kelpFullImage= ImageElement.as((new Image(kelpFullImageURI)).getElement());
	}

	private void loadBarReadyImages(){
		SafeUri crabConeURI = HermitCrabResources.INSTANCE.crabCone().getSafeUri();
		crabImage[coneCrab]= ImageElement.as((new Image(crabConeURI)).getElement());

		SafeUri crabLeftHandedURI = HermitCrabResources.INSTANCE.crabLeftHanded().getSafeUri();
		crabImage[leftHandedCrab]= ImageElement.as((new Image(crabLeftHandedURI)).getElement());

		SafeUri crabHiddenURI = HermitCrabResources.INSTANCE.crabHidden().getSafeUri();
		crabImage[hiddenCrab]= ImageElement.as((new Image(crabHiddenURI)).getElement());

		SafeUri crabElegantURI = HermitCrabResources.INSTANCE.crabElegant().getSafeUri();
		crabImage[elegantCrab]= ImageElement.as((new Image(crabElegantURI)).getElement());

		SafeUri crabJewelledURI = HermitCrabResources.INSTANCE.crabJewelled().getSafeUri();
		crabImage[jewelledCrab]= ImageElement.as((new Image(crabJewelledURI)).getElement());
	}

	private void loadCrabLostPositions(){
		crabLostPosistions[coneCrab] 		= coneLostPosition;
		crabLostPosistions[leftHandedCrab] 	= leftHandedLostPosition;
		crabLostPosistions[hiddenCrab] 		= hiddenLostPosition;
		crabLostPosistions[elegantCrab] 	= elegantLostPosition;
		crabLostPosistions[jewelledCrab] 	= jewelledLostPosition;
	}

	private void loadCrabInShellImages(){
		SafeUri shellConeIsHomeURI = HermitCrabResources.INSTANCE.shellWithCone().getSafeUri();
		shellWithCrabImage[coneCrab]= ImageElement.as((new Image(shellConeIsHomeURI)).getElement());
		SafeUri shellLeftHandedIsHomeURI = HermitCrabResources.INSTANCE.shellWithLeftHanded().getSafeUri();
		shellWithCrabImage[leftHandedCrab]= ImageElement.as((new Image(shellLeftHandedIsHomeURI)).getElement());
		SafeUri shellHiddenIsHomeURI = HermitCrabResources.INSTANCE.shellWithHidden().getSafeUri();
		shellWithCrabImage[hiddenCrab]= ImageElement.as((new Image(shellHiddenIsHomeURI)).getElement());
		SafeUri shellElegantIsHomeURI = HermitCrabResources.INSTANCE.shellWithElegant().getSafeUri();
		shellWithCrabImage[elegantCrab]= ImageElement.as((new Image(shellElegantIsHomeURI)).getElement());
		SafeUri shellJewelledIsHomeURI = HermitCrabResources.INSTANCE.shellWithJewelled().getSafeUri();
		shellWithCrabImage[jewelledCrab] = ImageElement.as((new Image(shellJewelledIsHomeURI)).getElement());
	}

	private void loadCrabIsLostImages(){
		SafeUri coneCrabDoneURI = HermitCrabResources.INSTANCE.crabConeDone().getSafeUri();
		lostCrabImage[coneCrab] = ImageElement.as((new Image(coneCrabDoneURI)).getElement());
		SafeUri lefthandedCrabDoneURI = HermitCrabResources.INSTANCE.crabLeftHandedDone().getSafeUri();
		lostCrabImage[leftHandedCrab] = ImageElement.as((new Image(lefthandedCrabDoneURI)).getElement());
		SafeUri hiddenCrabDoneURI = HermitCrabResources.INSTANCE.crabHiddenDone().getSafeUri();
		lostCrabImage[hiddenCrab] = ImageElement.as((new Image(hiddenCrabDoneURI)).getElement());
		SafeUri elegantCrabDoneURI = HermitCrabResources.INSTANCE.crabElegantDone().getSafeUri();
		lostCrabImage[elegantCrab] = ImageElement.as((new Image(elegantCrabDoneURI)).getElement());
		SafeUri jewelledCrabDoneURI = HermitCrabResources.INSTANCE.crabJewelledDone().getSafeUri();
		lostCrabImage[jewelledCrab] = ImageElement.as((new Image(jewelledCrabDoneURI)).getElement());
	}

	private void loadAnimationImages(){

		//Go Into Shell Start
		SafeUri coneGoHomeURI = HermitCrabResources.INSTANCE.coneGoHomeAnimated().getSafeUri();
		crabGoingHomeAnimImage[coneCrab]= ImageElement.as((new Image(coneGoHomeURI)).getElement());    	
		SafeUri leftHandedGoHomeURI = HermitCrabResources.INSTANCE.leftHandedGoHomeAnimated().getSafeUri();
		crabGoingHomeAnimImage[leftHandedCrab]= ImageElement.as((new Image(leftHandedGoHomeURI)).getElement());    	
		SafeUri hiddenGoHomeURI = HermitCrabResources.INSTANCE.hiddenGoHomeAnimated().getSafeUri();
		crabGoingHomeAnimImage[hiddenCrab]= ImageElement.as((new Image(hiddenGoHomeURI)).getElement());    	
		SafeUri elegantGoHomeURI = HermitCrabResources.INSTANCE.elegantGoHomeAnimated().getSafeUri();
		crabGoingHomeAnimImage[elegantCrab]= ImageElement.as((new Image(elegantGoHomeURI)).getElement());    	
		SafeUri jewelledGoHomeURI = HermitCrabResources.INSTANCE.jewelledGoHomeAnimated().getSafeUri();
		crabGoingHomeAnimImage[jewelledCrab]= ImageElement.as((new Image(jewelledGoHomeURI)).getElement());
		//Go Into Shell End

		//Eat Kelp Start
		SafeUri coneEatKelpAnimationURI = HermitCrabResources.INSTANCE.eatKelpCone().getSafeUri();
		crabEatKelpAnimImage[coneCrab] = ImageElement.as((new Image(coneEatKelpAnimationURI)).getElement());    	
		SafeUri leftHandedEatKelpAnimationURI = HermitCrabResources.INSTANCE.eatKelpLeftHanded().getSafeUri();
		crabEatKelpAnimImage[leftHandedCrab] = ImageElement.as((new Image(leftHandedEatKelpAnimationURI)).getElement());    	
		SafeUri hiddenEatKelpAnimationURI = HermitCrabResources.INSTANCE.eatKelpHidden().getSafeUri();
		crabEatKelpAnimImage[hiddenCrab] = ImageElement.as((new Image(hiddenEatKelpAnimationURI)).getElement());    	
		SafeUri elegantEatKelpAnimationURI = HermitCrabResources.INSTANCE.eatKelpElegant().getSafeUri();
		crabEatKelpAnimImage[elegantCrab] = ImageElement.as((new Image(elegantEatKelpAnimationURI)).getElement());    	
		//Note, Jewelled crab and Cone crab animations are the same
		crabEatKelpAnimImage[jewelledCrab] = ImageElement.as((new Image(coneEatKelpAnimationURI)).getElement());   
		//Eat Kelp End

		SafeUri netAnimationURI = HermitCrabResources.INSTANCE.netAnimation().getSafeUri();
		netAnimationImage = ImageElement.as((new Image(netAnimationURI)).getElement());
	}

	private void loadGameOverImages(){
		SafeUri gameOver0URI = HermitCrabResources.INSTANCE.gameOver0().getSafeUri();
		gameOverImage[0] =  ImageElement.as((new Image(gameOver0URI )).getElement());
		SafeUri gameOver1URI = HermitCrabResources.INSTANCE.gameOver1().getSafeUri();
		gameOverImage[1] =  ImageElement.as((new Image(gameOver1URI )).getElement());
		SafeUri gameOver2URI = HermitCrabResources.INSTANCE.gameOver2().getSafeUri();
		gameOverImage[2] =  ImageElement.as((new Image(gameOver2URI )).getElement());
		SafeUri gameOver3URI = HermitCrabResources.INSTANCE.gameOver3().getSafeUri();
		gameOverImage[3] =  ImageElement.as((new Image(gameOver3URI )).getElement());
		SafeUri gameOver4URI = HermitCrabResources.INSTANCE.gameOver4().getSafeUri();
		gameOverImage[4] =  ImageElement.as((new Image(gameOver4URI )).getElement());
		SafeUri gameOver5URI = HermitCrabResources.INSTANCE.gameOver5().getSafeUri();
		gameOverImage[5] =  ImageElement.as((new Image(gameOver5URI )).getElement());

		SafeUri restartImageURI = HermitCrabResources.INSTANCE.restartImage().getSafeUri();
		restartImage =  ImageElement.as((new Image(restartImageURI)).getElement());
	}

	private void loadSoundFX(){
		if (eatSoundFX == null) {
			//RootPanel.get().add(new Label("Audio is not supported by the browser"));
			canPlayEat= false;
		} else {
			AudioElement element = eatSoundFX.getAudioElement();
			String canPlayMP3 = element.canPlayType(AudioElement.TYPE_MP3);
			if(canPlayMP3.equalsIgnoreCase(MediaElement.CANNOT_PLAY)){
				//RootPanel.get().add(new Label("MP3 audio is not supported by the browser"));

				canPlayEat= false;
			} else {
				element.setSrc(HermitCrabResources.INSTANCE.biteKelp().getSafeUri().asString());
				eatSoundFX.setLoop(false);
				RootPanel.get().add(eatSoundFX);
				canPlayEat= true;
			}
		}
	}
	//LOAD End *******************************************	

	//SOUND Start*******************************************
	public void eatFXTurnOn(){
		//the Can Play check safeguards against calling audio commands when no audio is available
		if(canPlayEat){
			eatSoundFX.play();					
		}
	}

	public void eatFXTurnOff(){
		//the Can Play check safeguards against calling audio commands when no audio is available
		if(canPlayEat){
			eatSoundFX.pause();					
		}
	}
	//SOUND End *******************************************

	private void updateItemGridLocations(){
		for(int currentItem = coneShell; currentItem <= kelpItem3 ; currentItem++){
			this.gameItemGridLocations[currentItem][xLoc] = ((gameItemXYLocations[currentItem][xLoc])/itemPixelSize);
			this.gameItemGridLocations[currentItem][yLoc] = ((gameItemXYLocations[currentItem][yLoc])/itemPixelSize);
		}		
	}

	private int randomMapLocationX(int currentItem){
		//Map divides into 9 squares (3x3). 1 item will go into each of the 8 outside squares.
		//Each area is 10x10 squares. Get a random value from 1 to 10 to see where to put it
		int randomX =(int) (Math.random()* (10)+ 1);

		//don't let the square chosen be on the farthest left or right. Crab can't reach that.
		if(quadrantLocations[currentItem]== topLeft || 
				quadrantLocations[currentItem]== middleLeft || 
				quadrantLocations[currentItem]== bottomLeft){
			if(randomX ==1){
				randomX = 2;
			}			
			if(randomX >8){
				randomX = 8;
			}			
		}

		if(quadrantLocations[currentItem]== topCenter ||
				quadrantLocations[currentItem]== bottomCenter){
			randomX = randomX + 10; //shift from the left quadrants to the middle ones, 10 away.			
		}

		if(quadrantLocations[currentItem]== topRight || 
				quadrantLocations[currentItem]== middleRight ||
				quadrantLocations[currentItem]== bottomRight){
			if(randomX >8){
				randomX = 8;//We use 8 because the crab can't reach grid areas under 9 and 10
			}
			if(randomX <3){
				randomX = 3;
			}			
			randomX = randomX + 20; //shift from the left quadrants to the end ones, 20 away.
		}
		//Grid are spaced apart the length of the items (last setting: 50 px.)
		return (int) randomX * itemPixelSize; 
	}

	private int randomMapLocationY(int currentItem){
		//Map divides into 9 squares (3x3). 1 item will go into each of the 8 outside squares.
		//Each area is 10x10 squares. Get a random value from 1 to 10 to see where to put it
		int randomY =(int) (Math.random()* (10)+ 1);

		//don't let the square chosen be on the farthest top or bottom. Crab can't reach that.
		if(quadrantLocations[currentItem]== topLeft|| 
				quadrantLocations[currentItem]== topCenter || 
				quadrantLocations[currentItem]== topRight){
			if(randomY ==1){
				randomY = 2;
			}
			if(randomY >8){
				randomY = 8;
			}			
		}
		if(quadrantLocations[currentItem]== middleLeft || 
				quadrantLocations[currentItem]== middleRight){
			randomY = randomY + 10; //shift from the top quadrants to the middle ones, 10 away.
		}
		if(quadrantLocations[currentItem]== bottomLeft || 
				quadrantLocations[currentItem]== bottomCenter ||
				quadrantLocations[currentItem]== bottomRight){
			if(randomY >7){
				randomY = 7; //We use 7 because the crab can't reach grid areas under 8,9, and 10 
			}
			if(randomY <3){
				randomY = 3;
			}			
			randomY = randomY + 20; //shift from the top quadrants to the bottom ones, 20 away.
		}
		//Grid are spaced apart the length of the items (last setting: 50 px.)
		return (int) randomY * itemPixelSize; 
	}

	private void fillQuadrants(){
		//Map divides into 8 areas (top, bottom, left, right, upper left, upper right.. etc)
		//Put 1 thing into each of the 8 areas to spread it out. This sub fills an 8 member array with
		// unique values from 1 to 8
		int currentRandomPossibility =0;

		//Items list from coneShell(#1) up to kelpFoofd3(#8)
		quadrantLocations[coneShell] =(int) (Math.random()* (8)+ 1); // random 1 - 8
		boolean listHasDuplicates = true;
		boolean foundDuplicate = false;		
		//Logic. Add a random # to the list. Go back over the list to make sure it is unique
		//if it is, keep. If not, new random.
		for(int currentItemsArea = 2 ; currentItemsArea <= 8; currentItemsArea++){

			while(listHasDuplicates){
				currentRandomPossibility =(int) (Math.random()* (8)+ 1); // random 1 - 8
				foundDuplicate = false;
				for(int currentListCheck = 1; currentListCheck <= currentItemsArea; currentListCheck++){
					if(quadrantLocations[currentListCheck] == currentRandomPossibility){
						foundDuplicate= true;
					}
				}
				listHasDuplicates = foundDuplicate;
			}
			quadrantLocations[currentItemsArea] = currentRandomPossibility;
			listHasDuplicates = true; //reset for next loop
		}
		/*RootPanel.get().add(new Label("A:"+quadrantLocations[1]+
									  "  B:"+quadrantLocations[2]+
									  "  C:"+quadrantLocations[3]+
									  "  D:"+quadrantLocations[4]+
									  "  E:"+quadrantLocations[5]+
									  "  F:"+quadrantLocations[6]+
									  "  G:"+quadrantLocations[7]+
									  "  H:"+quadrantLocations[8]));*/

	}

	private boolean itemIsVisible(int itemLocX, int itemLocY){
		if(itemLocX + itemPixelSize > topLeftMapVisibleX && itemLocX < bottomRightMapDrawX &&
				itemLocY + itemPixelSize > topLeftMapVisibleY && itemLocY < bottomRightMapDrawY){
			return true;
		}
		return false;
	}

	//update where on the canvas the item should be drawn
	private void updateDrawOnCanvasXY(int itemToUpdate,int itemLocX, int itemLocY,
			int mapCanvasDrawStartX, int mapCanvasDrawStartY){
		gameItemCurrentCanvasXY[itemToUpdate][xLoc] = itemLocX + mapCanvasDrawStartX;
		gameItemCurrentCanvasXY[itemToUpdate][yLoc] = itemLocY + mapCanvasDrawStartY;
	}

	//GET AND SET Start *****************************************
	// GET Start*******************************
	public int getItemCount(){
		return gameItemCount;
	}

	public int getItemXGridLocation(int itemIDNumber){
		return gameItemGridLocations[itemIDNumber][xLoc];		
	}

	public int getItemYGridLocation(int itemIDNumber){
		return gameItemGridLocations[itemIDNumber][yLoc];		
	}

	private int getNumberCrabsHome(){
		int crabHomeCount = 0;
		canvas.getContext2d().drawImage(blackBarImage, 0, 0,canvasWidth,barHeight); //Black top strip
		for(int homeCheck = 1;homeCheck<=5; homeCheck++){
			if(sideLineStatus[homeCheck] == 3){
				crabHomeCount++;
			}
		}

		return crabHomeCount ;
	}

	public int getCurrentCrabsStatus(int currentCrab){
		return sideLineStatus[currentCrab];
	}

	public boolean crabCanGoHome(int currentCrab){
		if (crabGoingHomeFrame > animationLastFame[currentCrab]){
			itemImages[currentCrab] = shellWithCrabImage[currentCrab];
			//119 gives 48 refreshes (2 seconds more) of doing nothing to let the animation "rest" before continuing.
			if (crabGoingHomeFrame > 119){
				//coneCrabIsNotHome = false;
				sideLineStatus[currentCrab]=statusInHome;
			}
		}
		if(sideLineStatus[currentCrab]==statusInHome){
			crabGoingHomeFrame = 0; //reset frame for next animation
			return false;

		}else{
			return true;
		}
	}

	public boolean crabAteKelpLeaf(){
		return crabAteAKelpLeaf;
	}

	public boolean crabHasNotEatenThisKelp(int currentKelp){ 
		boolean thisKelpWasNotEaten = true, thisKelpWasEaten = false;
		for(int kelpLeaf = firstKelpLeaf; kelpLeaf <= lastKelpLeaf; kelpLeaf++){
			if(kelpNotEaten[currentKelp][kelpLeaf]){
				return thisKelpWasNotEaten;
			}
		}
		return thisKelpWasEaten ;
	}

	public boolean thisKelpIsGone(int currentKelp){
		//Return true if the kelp has been entirely eaten, else false
		return kelpItemIsGone[currentKelp];
	}

	public boolean crabIsBeingRemoved(){
		//Return false if the current crab has never finished the "go home" animation, else true

		if (lostCrabFrame > lostCrabLastFrame + 30){
			lostCrabAnimantionStillGoing = false;
			lostCrabFrame =0; netCanvasX = canvasWidth + itemPixelSize;
			//RootPanel.get().add(new Label("lostCrabAnimantionStillGoing: False"));
		}

		return lostCrabAnimantionStillGoing;
	}

	public boolean gameOverAnimationIsComplete(){
		return gameEnded;
	}

	public boolean restartTouched(int xTouched, int yTouched){
		if(restartXDraw <= xTouched&& xTouched <= restartXDraw + restartWidth &&
				restartYDraw <= xTouched&& xTouched <= restartYDraw + restartHeight){
			return true;
		}
		return false;
	}

	// GET End*******************************

	// SET Start*******************************
	public void setCurrentCrab(int gameCrabCurrent){
		currentPlayerCrab = gameCrabCurrent;
	}

	public void clearCrabAteAKelp(){
		crabAteAKelpLeaf = false;
	}


	//If a crab is to be removed, lostCrabAnimantionStillGoing becomes true as that process begins
	public void setRemoveCrabNow(){
		lostCrabAnimantionStillGoing = true;
	}
	// SET End*******************************
	//GET AND SET End *****************************************

	//DRAWINGS Start ************************************************
	public void draw(int animationID, int gamePlayerMapX, int gamePlayerMapY,
			int gamePlayerCanvasX,int gamePlayerCanvasY, int mapCanvasDrawStartX, int mapCanvasDrawStartY,
			int gameCurrentPlayerCrab){
		canvas.getContext2d().clearRect(0, 0,canvasWidth,canvasHeight);
		topLeftMapVisibleX = gamePlayerMapX - gamePlayerCanvasX;
		topLeftMapVisibleY = gamePlayerMapY - gamePlayerCanvasY;
		bottomRightMapDrawX = topLeftMapVisibleX + (canvasWidth-controlBarThickness);
		bottomRightMapDrawY = topLeftMapVisibleY + (canvasHeight-controlBarThickness);
		currentPlayerCanvasX = gamePlayerCanvasX;
		currentPlayerCanvasY = gamePlayerCanvasY;
		currentPlayerCrab = gameCurrentPlayerCrab;

		//	Check the X,Y location of each item. Draw if its visible in the exposed area of the map  
		for(int currentItem = coneShell; currentItem <= kelpItem3 ; currentItem++){
			currentItemLocX = gameItemXYLocations[currentItem][xLoc];
			currentItemLocY = gameItemXYLocations[currentItem][yLoc];

			itemCurrentImage = itemImages[currentItem];
			if(itemIsVisible(currentItemLocX,currentItemLocY)){
				updateDrawOnCanvasXY(currentItem,currentItemLocX,currentItemLocY,mapCanvasDrawStartX,mapCanvasDrawStartY);
				canvas.getContext2d().drawImage(itemCurrentImage,
						gameItemCurrentCanvasXY[currentItem][xLoc],gameItemCurrentCanvasXY[currentItem][yLoc],
						itemPixelSize, itemPixelSize); 

				//Draw Kelp leaves if item is kelp
				if(kelpItem1 <= currentItem && currentItem <= kelpItem3){
					//kelpLeafAnim1Image  kelpFrame*itemPixelSize
					if(kelpNotEaten[currentItem][firstKelpLeaf]){
						canvas.getContext2d().drawImage(kelpLeafAnim1Image,kelpCurrentFrame,0,itemPixelSize,itemPixelSize,
								gameItemCurrentCanvasXY[currentItem][xLoc],gameItemCurrentCanvasXY[currentItem][yLoc],
								itemPixelSize, itemPixelSize);
					}
					if(kelpNotEaten[currentItem][secondKelpLeaf]){		  
						canvas.getContext2d().drawImage(kelpLeafAnim2Image,kelpCurrentFrame,0,itemPixelSize,itemPixelSize,
								gameItemCurrentCanvasXY[currentItem][xLoc],gameItemCurrentCanvasXY[currentItem][yLoc],
								itemPixelSize, itemPixelSize);
					}
					if(kelpNotEaten[currentItem][thirdKelpLeaf]){
						canvas.getContext2d().drawImage(kelpLeafAnim3Image,kelpCurrentFrame,0,itemPixelSize,itemPixelSize,
								gameItemCurrentCanvasXY[currentItem][xLoc],gameItemCurrentCanvasXY[currentItem][yLoc],
								itemPixelSize, itemPixelSize);
					}
					if(kelpNotEaten[currentItem][lastKelpLeaf]){
						canvas.getContext2d().drawImage(kelpLeafAnim4Image,kelpCurrentFrame,0,itemPixelSize,itemPixelSize,
								gameItemCurrentCanvasXY[currentItem][xLoc],gameItemCurrentCanvasXY[currentItem][yLoc],
								itemPixelSize, itemPixelSize);
					}
				} //if IsKelp? ends
			} //If Visible condition ends
		} //For each item Loop ends
		kelpFrame ++;
		if(kelpFrame > kelpLastFrame){
			kelpFrame = 0; //Loops the kelp animation by stating over
		} //The animation is a single strip of images. Each frame is 1 image length (50 px) from the last.
		kelpCurrentFrame = kelpFrame*itemPixelSize; //So if the frame is on 3, then grab frame image from 3 * 50, = 150px
		clearCanvasBorders(); //keeps anything from being drawn on the black control edges of the canvas
		blackOutTankBar();
		//If a shell is found by the player, or any event is happening, this is where it is caught and drawn
		if(animationID>0){
			drawAnimation(animationID, currentPlayerCrab);
		}
		//As an animation runs, keeps the crab images on the control bar updated, as they may be being affected or covered
		updateBar(); //Bar images are the crabs displayed on the Control bar
		updateTank();//  in either the "ready to go" side, or "dead" side if they are lost
	}

	public void drawAnimation(int animationID, int currentCrab){
		if(animationID >0){
			switch (animationID) {
			case correctShellFound:
				runCrabEnterShellAnimation(currentCrab);
				break;

			case lostACrab:
				runLostACrabAnimation(currentCrab);
				break;

			case kelpItem1:
				if(!kelpItemIsGone[kelpItem1]){
					runCrabEatsKelp(currentCrab, kelpItem1);
				}
				break;

			case kelpItem2:
				if(!kelpItemIsGone[kelpItem2]){
					runCrabEatsKelp(currentCrab, kelpItem2);
				}
				break;

			case kelpItem3:
				if(!kelpItemIsGone[kelpItem3]){
					runCrabEatsKelp(currentCrab, kelpItem3);
				}
				break;

			case gameOver:if(gameOverFrame > animationLastFame[gameOver]){gameOverFrame =animationLastFame[gameOver];} 

			canvas.getContext2d().drawImage(gameOverImage[getNumberCrabsHome()],100,gameOverCanvasY);
			gameOverCanvasY= gameOverCanvasY+4;
			if(gameOverCanvasY > 100){
				gameOverCanvasY = 100;
				gameEnded = true;
				canvas.getContext2d().drawImage(restartImage,100,gameOverCanvasY+250);
			}
			break;
			}
		}
	}

	private void runCrabEnterShellAnimation(int currentCrab){
		if (sideLineStatus[currentCrab] < 3){
			// draw next frame of crab going home animation
			if(crabGoingHomeFrame <= animationLastFame[currentCrab]){
				canvas.getContext2d().drawImage(crabGoingHomeAnimImage[currentCrab],
						crabGoingHomeFrame * itemPixelSize, 0,itemPixelSize, itemPixelSize,
						gameItemCurrentCanvasXY[currentCrab][xLoc],gameItemCurrentCanvasXY[currentCrab][yLoc],
						itemPixelSize, itemPixelSize);
			}
			crabGoingHomeFrame++;
		}
	}

	private void runCrabEatsKelp(int currentCrab, int currentKelp){
		int currentLeaf = 0;
		if(kelpEatFrame<=kelpEatLastFrame){
			canvas.getContext2d().drawImage(crabEatKelpAnimImage[currentCrab],
					kelpEatFrame * itemPixelSize, 0,itemPixelSize, itemPixelSize,
					gameItemCurrentCanvasXY[currentKelp][xLoc],gameItemCurrentCanvasXY[currentKelp][yLoc],
					itemPixelSize, itemPixelSize);
			if((kelpEatFrame+5) % 18 == 0){ //play the bite sound on the 13th of every 18 frames 
				eatFXTurnOn();
				crabAteAKelpLeaf = true;
				currentLeaf = kelpEatFrame/18;
				kelpNotEaten[currentKelp][currentLeaf] = false;
				//RootPanel.get().add(new Label("KelpFrame: "+kelpEatFrame +" -Munch"));
			}
			kelpEatFrame++;
		}else{
			kelpEatFrame =0;
			kelpItemIsGone[currentKelp]=true;
		}
	}

	private void runLostACrabAnimation(int currentCrab){

		if (lostCrabAnimantionStillGoing){  //Crab health ran out. A net comes in and scoops it up.
			currentLostCrabImage = lostCrabImage[currentCrab];
			paintBlackBorders();		
			// draw next frame of crab removal animation
			if(lostCrabFrame < twoSeconds){
				moveNetToCrab();
			}
			if(twoSeconds <= lostCrabFrame && lostCrabFrame <= lostCrabLastFrame){
				scoopCrabInNet();
			}
			if(lostCrabFrame > lostCrabLastFrame && lostCrabFrame <= lostCrabLastFrame + 10){
				raiseNetWithCrabPriorToDrop();
			}
			if(lostCrabFrame  > lostCrabLastFrame + 10 && lostCrabFrame <= lostCrabLastFrame + 20){
				dropNetAndCrab();
			}

			if(lostCrabFrame  > lostCrabLastFrame + 20){
				dropNetOutOfSightButLeaveCrab();	
			}
			lostCrabFrame++;
		}
	}

	private void moveNetToCrab(){
		int netFrameX,netFrameY;
		crabCanvasX = currentPlayerCanvasX;
		crabCanvasY = currentPlayerCanvasY;

		//Divide the distance from the net image to the crab by the 2 seconds (48 frames)
		//  it will take to reach the crab and perform the scoop. That = # of pixels to move net per tick
		netCanvasXIncrement = (netStartingXPosition - currentPlayerCanvasX)/twoSeconds;

		//The net scoop animation is a single image of 10 frames(columns) a row, for 6 rows.
		//To grab the next frame, you need to resolve the row and column to values from 0 up to the last row or column.
		//Below takes the current frame, 13 for example, converts it to row #1, column #2 (both start at 0)
		//Multiply: x= (column)2*(frame width)400 =800, y=(row)1*(frame height)180=180.
		//  The x,y top left corner of frame 13 is 800,180
		netFrameX = (lostCrabFrame % columsOfNetAnimation) *netWidthPx;
		netFrameY = (lostCrabFrame /columsOfNetAnimation) *netHeightPx;

		//Move 1/48th the start distance of the net toward the player (for the next 48 frames).
		netCanvasX= netCanvasX - netCanvasXIncrement;
		netCanvasY = currentPlayerCanvasY-netHeightAdjustment;
		drawNetAndCrab(netFrameX,netFrameY);
	}

	private void scoopCrabInNet(){
		int netFrameX,netFrameY;
		netFrameX = (lostCrabFrame % columsOfNetAnimation) *netWidthPx;
		netFrameY = (lostCrabFrame /columsOfNetAnimation) *netHeightPx;
		netCanvasX = currentPlayerCanvasX -itemPixelSize; 
		crabCanvasXIncrement = (currentPlayerCanvasX -crabLostPosistions[currentPlayerCrab])/10;
		crabCanvasYIncrement =((canvasWidth+itemPixelSize)+ - currentPlayerCanvasY)/10;
		drawNetAndCrab(netFrameX,netFrameY);
	}

	private void updateBar(){
		canvas.getContext2d().drawImage(blackBarImage, //Black out the bar first, then draw the crabs
				crabOnStartBarX,crabOnBarY,barWidth,barHeight);

		for(int currentBarImage = coneCrab; currentBarImage <=jewelledCrab; currentBarImage++){
			if(sideLineStatus[currentBarImage]== statusOnBarReady){

				int barX = crabOnTankBarX, barY = crabOnBarY;

				switch (currentBarImage) {
				case coneCrab: 
					barX=coneStartPosition; 
					break;
				case leftHandedCrab: 
					barX=leftHandedStartPosition; 
					break;
				case hiddenCrab: 
					barX=hiddenStartPosition; 
					break;
				case elegantCrab: 
					barX=elegantStartPosition; 
					break;
				case jewelledCrab: 
					barX=jewelledStartPosition; 
					break;
				}
				canvas.getContext2d().drawImage(crabImage[currentBarImage],
						barX,barY,itemPixelSize,itemPixelSize);
			}
		}
	}

	private void updateTank(){

		for(int currentBarImage = coneCrab; currentBarImage <=jewelledCrab; currentBarImage++){
			if(sideLineStatus[currentBarImage]== statusInTankSpot){
				int barX = crabOnTankBarX, barY = crabOnBarY;

				switch (currentBarImage) {
				case 1: 
					barX=coneLostPosition; 
					break;
				case 2: 
					barX=leftHandedLostPosition; 
					break;
				case 3: 
					barX=hiddenLostPosition; 
					break;
				case 4: 
					barX=elegantLostPosition; 
					break;
				case 5: 
					barX=jewelledLostPosition; 
					break;
				}
				canvas.getContext2d().drawImage(lostCrabImage[currentBarImage],
						barX,barY,itemPixelSize,itemPixelSize);
			}
		}
	}

	private void raiseNetWithCrabPriorToDrop(){
		crabCanvasX = crabCanvasX - crabCanvasXIncrement;
		crabCanvasY = crabCanvasY - netDropSpeed ;
		netCanvasX = crabCanvasX-netWidthAdjustment ;
		netCanvasY = crabCanvasY-netHeightAdjustment;
		drawNetAndCrab(lastNetFrameX,lastNetFrameY);
	}

	private void dropNetAndCrab(){
		if(crabCanvasX != crabLostPosistions[currentPlayerCrab]){
			crabCanvasX =crabLostPosistions[currentPlayerCrab];
		}
		crabCanvasY = crabCanvasY + crabCanvasYIncrement;
		netCanvasX = crabCanvasX-netWidthAdjustment;
		netCanvasY = crabCanvasY-netHeightAdjustment;
		drawNetAndCrab(lastNetFrameX,lastNetFrameY);
	}

	private void dropNetOutOfSightButLeaveCrab (){
		netCanvasY = netCanvasY + crabCanvasYIncrement;
		canvas.getContext2d().drawImage(netAnimationImage,
				lastNetFrameX,lastNetFrameY,netWidthPx, netHeightPx,
				netCanvasX,netCanvasY,netWidthPx, netHeightPx);
		sideLineStatus[currentPlayerCrab]= statusInTankSpot;
		//RootPanel.get().add(new Label("NetFrame: "+lostCrabFrame));
	}

	public void clearCrabOnBar(int crabToClear){
		//This function puts a black square over the next crab to deploy
		// where it sat waiting on the black control bar, "erasing" it.
		int barX = crabOnTankBarX, barY = crabOnBarY;

		switch (crabToClear) {
		case coneCrab: 
			barX=coneStartPosition;
			break;
		case leftHandedCrab: 
			barX=leftHandedStartPosition; 
			break;
		case hiddenCrab: 
			barX=hiddenStartPosition; 
			break;
		case elegantCrab: 
			barX=elegantStartPosition; 
			break;
		case jewelledCrab: 
			barX=jewelledStartPosition; 
			break;
		}
		sideLineStatus[crabToClear]= statusInPlay;
		canvas.getContext2d().drawImage(blackBarImage,barX,barY,itemPixelSize,itemPixelSize);
	}

	private void drawNetAndCrab(int netFrameX, int netFrameY){
		canvas.getContext2d().drawImage(currentLostCrabImage,
				crabCanvasX,crabCanvasY,50,50);

		canvas.getContext2d().drawImage(netAnimationImage,
				netFrameX, netFrameY,netWidthPx, netHeightPx,
				netCanvasX,netCanvasY,netWidthPx, netHeightPx);
		/*RootPanel.get().add(new Label("netCanvasX: "+netCanvasX+
									  "  CrabLostPos: "+crabLostPosistions[currentPlayerCrab]+
									  "  Crab ID: "+currentPlayerCrab)); */
	}

	private void clearCanvasBorders(){
		canvas.getContext2d().clearRect(0, 0,canvasWidth,50); //Clear top strip
		canvas.getContext2d().clearRect(0, 0,50,canvasHeight); //Clear Left strip
		canvas.getContext2d().clearRect(canvasWidth - 50, 0,50,canvasHeight); //Clear Right strip
		canvas.getContext2d().clearRect(0, canvasHeight - 50,canvasWidth,50); //Clear bottom strip
	}

	private void paintBlackBorders(){
		canvas.getContext2d().drawImage(blackBarImage, 0, 0,canvasWidth,50); //Black top strip
		canvas.getContext2d().drawImage(blackBarImage, 0, 0,50,canvasHeight); //Black Left strip
		canvas.getContext2d().drawImage(blackBarImage,canvasWidth - 50, 0,50,canvasHeight); //Black Right strip
		canvas.getContext2d().drawImage(blackBarImage,0, canvasHeight - 50,canvasWidth,50); //Black bottom strip
	}

	private void blackOutTankBar(){
		canvas.getContext2d().drawImage(blackBarImage, //Black out the bar first, then draw the crabs
				crabOnTankBarX,crabOnBarY,barWidth,itemPixelSize);
	}
	//DRAWINGS End ************************************************
}
